#pragma once

#include <linux/compiler.h>
#include <linux/bits.h>
#include <asm/bitops.h>

#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/non-atomic.h>

#define BITS_TO_LONGS(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long))

#define __set_bit(nr, addr) ___set_bit(nr, addr)
#define __clear_bit(nr, addr) ___clear_bit(nr, addr)
#define test_bit(nr, addr) _test_bit(nr, addr)
#define __test_and_clear_bit(nr, addr) ___test_and_clear_bit(nr, addr)

int constant_fls(unsigned int x);
#define fls(x) constant_fls(x)

extern unsigned int __sw_hweight8(unsigned int w);
extern unsigned int __sw_hweight16(unsigned int w);
extern unsigned int __sw_hweight32(unsigned int w);
extern unsigned long __sw_hweight64(u64 w);

/**
 * assign_bit - Assign value to a bit in memory
 * @nr: the bit to set
 * @addr: the address to start counting from
 * @value: the value to assign
 */
#define assign_bit(nr, addr, value) \
    ((value) ? set_bit((nr), (addr)) : clear_bit((nr), (addr)))

static inline unsigned long hweight_long(unsigned long w)
{
	return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
}
